[WPF] CheckListBox的实现方式分析 |
您所在的位置:网站首页 › wpf focusable › [WPF] CheckListBox的实现方式分析 |
实际项目中常常要实现有CheckBox列表框。但是WPF没有自带这样的一个控件,下面就用Style来实现这样的功能。而对于CheckBox列表框,又常常会有一个Select All的CheckBox来表示当前列表框的选择状态。这个功能也会被包含在下面的示例之中。效果如下图所示。
对于单纯的,没有后台数据绑定的情况下,这个功能可以用ItemContainerStyle来实现。代码如下: CheckListBoxItemContainerStyle
其中要对Content和ContentTemplate等属性进行绑定,以方便对其进行扩展,保证其通用性。这个Style一般会放在Application级别的Resource中。 对于有后台数据绑定的情况,一般会有双个属性要绑定,一个是CheckBox里的Content,一个是CheckBox的IsChecked。绑定的路径,只有在用一个Style的ListBox那里才知道,所以并不能写在这个Style里,否则会破坏这个Style的通用性。比较合理的方式是基于这个现有的Style进行修改。
对于下面的数据类。 DataItem Class public class DataItem : INotifyPropertyChanged{ private string name; private bool isEnabled; public string Name { get { return name; } set { name = value; OnPropertyChanged( " Name " ); } } public bool IsEnabled { get { return isEnabled; } set { isEnabled = value; OnPropertyChanged( " IsEnabled " ); } } #region INotifyPropertyChanged Members public event PropertyChangedEventHandler PropertyChanged; #endregion protected virtual void OnPropertyChanged( string propertyName) { PropertyChangedEventHandler temp = PropertyChanged; if (temp != null ) { temp( this , new PropertyChangedEventArgs(propertyName)); } }}
我们需要下面这个有针对性的Style来应用数据绑定。 DataItemCheckListBoxStyle
在上面的Style中,使用了ItemTemplate来指定CheckBox里的Content绑定到的属性,并把ListBoxItem的IsSelected绑定数据的相应属性上。由于这个Style是针对特定数据写的,所以应当放置在使用这个Style的ListBox所在的Window的Resource中。
当然,也可以为ListBox添加两个绑定类型的Attached Property来实现一个通用的Style。不过这个Property一样要在使用的地方设置,其实没有太大区别。有兴趣的读者可以自己试一下。
对于Select All这个CheckBox而言,用Attached Property倒是很方便。给CheckBox添加一个SyncTarget属性指向要同步的ListBox,就可以在Window.xaml.cs之外的地方同步CheckBox和ListBox了。代码如下: ToggleButtonProperty public class ToggleButtonProperty{ // Using a DependencyProperty as the backing store for SyncTarget. This enables animation, styling, binding, etc... public static readonly DependencyProperty SyncTargetProperty = DependencyProperty.RegisterAttached( " SyncTarget " , typeof (ListBox), typeof (ToggleButtonProperty), new UIPropertyMetadata( new PropertyChangedCallback(OnSyncTargetChanged))); public static ListBox GetSyncTarget(DependencyObject obj) { return obj.GetValue(SyncTargetProperty) as ListBox; } public static void SetSyncTarget(DependencyObject obj, ListBox value) { obj.SetValue(SyncTargetProperty, value); } private static void OnSyncTargetChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) { ToggleButton checker = sender as ToggleButton; if (checker == null ) { throw new InvalidOperationException( " SyncTarget property only works on ToggleButton. " ); } ListBox targetList = e.NewValue as ListBox; if (targetList == null ) { throw new InvalidOperationException( " Sync target must be a ListBox. " ); } // TODO: Un-subscribe OldValue's Event. checker.Checked += (s, a) => { targetList.SelectAll(); }; checker.Unchecked += (s, a) => { targetList.UnselectAll(); }; targetList.SelectionChanged += (s, a) => { checker.IsChecked = targetList.SelectedItems.Count == 0 ? false : targetList.SelectedItems.Count == targetList.Items.Count ? ( bool ? ) true : null ; }; }}
使用方式也很简单。如下代码所示。 用法
完整的项目文件可以从这里下载。 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |